Spring 3引入了一些验证支持的增强。首先,JSR-303 Bean Validation API现在已经完全支持了。其次,在以编码的方式Spring的DataBinder时,他可以绑定对象并校验他们。第三,Spring MVC现在支持声明性的验证@Controller输入。

8.8.1 Overview of the JSR-303 Bean Validation API

JSR-303标准化了Java平台的约束声明和元数据。使用此API,你可以用声明性的约束注释model的属性,它们会在运行时被强制执行。 有许多内置的约束你可以使用。你也可以定义自己的约束。
为了说明,请考虑一个拥有两个属性的简单Person model:

public class PersonForm {
    private String name;
    private int age;
}

JSR-303允许你对这些属性使用约束性声明:

public class PersonForm {

    @NotNull
    @Size(max=64)
    private String name;

    @Min(0)
    private int age;

}

8.8.2 Configuring a Bean Validation Provider

Spring提供了对Bean Validation API的全完支持。这包括了方便的将JSR-303/JSR-349 Bean Validation提供者作为Spring Bean方便的加载。这允许javax.validation.ValidatorFactoryjavax.validation.Validator在你应用程序任何需要验证的地方呗注入。
使用LocalValidatorFactoryBean将默认的Validator配置为一个Spring Bean:

<bean id="validator"
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

上述基本的配置会通过它默认的运行机制初始化Bean Vlidation。被期待存在类路径下的JSR-303/JSR-349提供者,和Hebernate Validator,会被自动的检测。

Injecting a Validator

LocalValidatorFactoryBean同时实现了javax.validation.ValidatorFactoryjavax.validation.Validator,以及Spring的org.springframework,validation.Validator。你可以将这些接口的引用注入到需要调用验证逻辑的bean中。
如果你偏爱直接使用Bean Validation API,你可以注入一个javax.validation.Validator

import javax.validation.Validator;

@Service
public class MyService {

    @Autowired
    private Validator validator;

如果你的Bean需要Spring Validation API,那可以注入一个org.springframework.validation.Validator的引用:

import org.springframework.validation.Validator;

@Service
public class MyService {

    @Autowired
    private Validator validator;

}

Configuring Custom Constraints

每一个Bean Validation约束有两部分组成。首先,一个@Constraint注解用来声明约束和它配置的属性。其次,一个javax.validation.ConstraintValidation接口的实现类来实现约束的行为。为了联合声明和实现,每一个@Contraint注解引用了对应的校验约束的实现类。在运行时,ConstraintValidatorFactory会当在你领域模型中遇到约束性注解是实例化实现。
默认的,LocalValidatorFactoryBean配置了一个SpringConstriantValidatorFactory来通过Spring去创建ConstraintValidator实例。这允许你自定义的ConstraintValidators像其他任何Spring bean一样受益于依赖注入。
下面是一个自定义的@Constraint声明的例子,紧跟着的是和约束结合使用的ConstraintValidator实现,并且用到了Spring的依赖注入:

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyConstraint {
}
import javax.validation.ConstraintValidator;

public class MyConstraintValidator implements ConstraintValidator {

    @Autowired;
    private Foo aDependency;

    ...
}

正如你所见,一个ConstraintValidator实现能够像其他Spring bean一样有自己的依赖@Autowired。

Spring-driven Method Validation

Bean Validation 1.1和Hibernate Validator 4.3的自定义拓展提供了方法校验的特征,都可以通过MethdoValidationPostProcessorbean定义被集成到Spring上下文中:

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

为了符合Spring-驱动方法校验的条件,全部的类必须要用Spring的@Validated注解,可以选择声明使用的验证组。查看MethodValidationPostProcessorjava文档查看更过关于设置Hibernate Validator和Bean Validation1.1提供者的详情。

Additional Configuration Options

默认的LocalValidatorFactoryBean配置对为大部分情况是足够的。对于各种Bean Validation结构,有许多配置选项,从消息插入到遍历方式。查看LocalValidatorFactoryBeanjava文档查看这些选项的更多信息。

8.8.3 Configuring a DataBinder

从Spring 3起,一个DataBinder实例可以配置一个Validator。一旦被配置,调用binder.validate()时会调用Validator。校验错误会自动被添加到binder的BindingResult中。
当以代码的方式使用DataBinder时,可以在绑定目标对象之后调用校验逻辑:

Foo target = new Foo();
DataBinder binder = new DataBinder(target);
binder.setValidator(new FooValidator());

// bind to the target object
binder.bind(propertyValues);

// validate the target object
binder.validate();

// get BindingResult that includes any validation errors
BindingResult results = binder.getBindingResult();

一个DataBinder也可以通过dataBinder.addValidatorsdataBinder.replaceValidators来配置多个Validator实例。这在结合全局配置的Bean Validation到本地DataBinder实例上配置的Spring Validation时十分有用。